﻿#include "uedgebutton.h"
#include "style/ustylepainter.h"
#include "style/upalette.h"
#include "uapplication.h"

#include <QPainterPath>
#include <QStyleOptionButton>

constexpr int triangleHeight = 4;
constexpr int triangleWidth = 8;

class UEdgeButtonPrivate
{
public:
    UEdgeButtonPrivate(UEdgeButton* q) : q_ptr(q) {}
    ~UEdgeButtonPrivate() {}

    void backgroudPath(QPainterPath &path);

    void trianglePath(QPainterPath &path);

private:
    Q_DECLARE_PUBLIC(UEdgeButton)
    Q_DISABLE_COPY(UEdgeButtonPrivate)
    UEdgeButton* const q_ptr = nullptr;

    int backgroundRole = QPalette::Highlight;
    bool expand = false;
    Qt::Orientation orientation = Qt::Vertical;
};

void UEdgeButtonPrivate::backgroudPath(QPainterPath &path)
{
    Q_Q(UEdgeButton);
    if (Qt::Vertical == orientation) {
        path.moveTo(q->rect().topLeft());
        path.lineTo(q->width(), q->width());
        path.lineTo(q->width(), q->height() - q->width());
        path.lineTo(q->rect().x(), q->height());
    } else {
        path.moveTo(q->rect().bottomLeft());
        path.lineTo(q->rect().x() + q->height(), q->rect().y());
        path.lineTo(q->rect().x() + q->width() - q->height(), q->rect().y());
        path.lineTo(q->rect().bottomRight());
    }
    path.closeSubpath();
}

void UEdgeButtonPrivate::trianglePath(QPainterPath &path)
{
    Q_Q(UEdgeButton);
    if (Qt::Vertical == orientation) {
        if (expand) {
            path.moveTo((q->width() - triangleHeight)/2, q->height()/2);
            path.lineTo((q->width() - triangleHeight)/2 + triangleHeight, (q->height()/2 - triangleWidth/2));
            path.lineTo((q->width() - triangleHeight)/2 + triangleHeight, (q->height()/2 + triangleWidth/2));
        } else {
            path.moveTo((q->width() - triangleHeight)/2, (q->height()/2 - triangleWidth/2));
            path.lineTo((q->width() - triangleHeight)/2 + triangleHeight, q->height()/2);
            path.lineTo((q->width() - triangleHeight)/2, (q->height()/2 + triangleWidth/2));
        }
    } else {
        if (expand) {
            path.moveTo((q->width()/2 - triangleWidth/2), (q->height() - triangleHeight)/2);
            path.lineTo(q->width()/2, q->height()/2 + triangleHeight/2);
            path.lineTo((q->width()/2 + triangleWidth/2), (q->height() - triangleHeight)/2);
        } else {
            path.moveTo((q->width()/2 - triangleWidth/2), q->height()/2 + triangleHeight/2);
            path.lineTo(q->width()/2, (q->height() - triangleHeight)/2);
            path.lineTo((q->width()/2 + triangleWidth/2), q->height()/2 + triangleHeight/2);
        }
    }
    path.closeSubpath();
}

UEdgeButton::UEdgeButton(Qt::Orientation orientation, QWidget* parent) : QPushButton(parent)
    , d_ptr(new UEdgeButtonPrivate(this))
{
    Q_D(UEdgeButton);
    d->orientation = orientation;
    connect(this, &UEdgeButton::clicked, this, [=](){
        setExpand(!d->expand);
        emit expandChanged(d->expand);
    });
}

UEdgeButton::UEdgeButton(QWidget* parent) : QPushButton(parent)
    , d_ptr(new UEdgeButtonPrivate(this))
{
    Q_D(UEdgeButton);
    connect(this, &UEdgeButton::clicked, this, [=](){
        setExpand(!d->expand);
        emit expandChanged(d->expand);
    });
}

UEdgeButton::~UEdgeButton()
{
}

void UEdgeButton::setOrientation(Qt::Orientation orientation)
{
    Q_D(UEdgeButton);
    if (d->orientation != orientation)
    {
        d->orientation = orientation;
        update();
    }
}

void UEdgeButton::setBackgroundRole(int role)
{
    Q_D(UEdgeButton);
    if (d->backgroundRole != role)
    {
        d->backgroundRole = role;
        update();
    }
}

void UEdgeButton::setExpand(bool isExpand)
{
    Q_D(UEdgeButton);
    if (d->expand != isExpand)
    {
        d->expand = isExpand;
        update();
    }
}

bool UEdgeButton::isExpand()
{
    Q_D(UEdgeButton);
    return d->expand;
}

void UEdgeButton::paintEvent(QPaintEvent* event)
{
    Q_UNUSED(event)
    Q_D(UEdgeButton);

    QStyleOptionButton btn;
    initStyleOption(&btn);
    UStylePainter stylePainter(this);
    stylePainter.setRenderHints(QPainter::RenderHint::Antialiasing);

    QPainterPath path;
    d->backgroudPath(path);
    UPalette* palette = uApp->applicationPalette();
    QPalette::ColorGroup cg = UProxyStyle::colorGroup(&btn, this);
    QColor color = palette->color(cg, d->backgroundRole);
    if (btn.state & QStyle::State_Enabled)
    {
        if (btn.state & QStyle::State_Sunken || btn.state & QStyle::State_On)
        {
            color = color.darker(150);
        }
        else if (btn.state & QStyle::State_MouseOver)
        {
            color = color.darker(120);
        }
    }

    stylePainter.setPen(color);
    stylePainter.drawPath(path);

    QPainterPath trianglePath;
    d->trianglePath(trianglePath);
    stylePainter.fillPath(trianglePath, color);
}

QSize UEdgeButton::sizeHint() const
{
    Q_D(const UEdgeButton);
    if (Qt::Vertical == d->orientation)
    {
        return QSize(10, 80);
    }
    else
    {
        return QSize(80, 10);
    }
}
